import {useRoutes, useLocation,NonIndexRouteObject, Navigate} from 'react-router-dom';
import React from "react";
import {getLocalStorage} from "@/utils/localtion";
type ReactNode = React.ReactNode;

//meta规则
interface MetaRule {
    auth: boolean, //是否需要登录验证
    title: string, //页面title
    [name:string] : string | boolean, //其他参数
}

//单个路由规则
interface RouteObjectRule extends NonIndexRouteObject{
    children?: RouteObjectRule[];
    redirect?: string, //重定向地址
    meta?: MetaRule, //页面参数
}


interface GuardRule {
    routers: RouteObjectRule[], //路由对象
}

interface onRouteBeforeRule<meta = MetaRule , to = string> {
    (meta : meta, to : to) : string;
}


const onRouteBefore: onRouteBeforeRule = (meta, to) => {
    const {auth, title} = meta;
    if (title) {    // 动态修改页面title
        document.title = title || '统一认证';
    }
    // token权限验证
    return (auth && !getLocalStorage('accessToken')) ? '/login' : to;
};


//路由导航，设置redirect重定向 和auth权限
function Guard(element: ReactNode, meta: MetaRule) {
    //
    const {pathname} = useLocation();
    const nextPath = onRouteBefore(meta, pathname);
    if (nextPath && nextPath !== pathname) {
        element = <Navigate to={nextPath} replace={true}/>;
    }
    return element;
}


// 将自定义的routes转换为标准的routes
function transRoutes(routes: RouteObjectRule[]):RouteObjectRule[] {
    const list: RouteObjectRule[] = [];
    routes.forEach(route => {
        const obj = {...route};
        if (obj.redirect) {
            obj.element = <Navigate to={obj.redirect} replace={true}/>
        }
        if (obj.element) {
            if (obj?.meta) {
                obj.element = Guard(obj.element, obj.meta)
            }
        }
        if (obj.children) {
            obj.children = transRoutes(obj.children)
        }
        ['redirect', 'meta'].forEach(name => delete obj[name]);
        list.push(obj)
    });
    return list
}

export type {
    onRouteBefore,
    RouteObjectRule,
    MetaRule,
    onRouteBeforeRule,
    ReactNode,
}

export default function RouterGuard(params: GuardRule) {
    return useRoutes(transRoutes(params.routers)); //路由数组，进行加载，转换
}
